package com.eian.boot.common.core.utils;

import lombok.Getter;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.thread.Threading;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

/**
 * spring上下文工具类
 *
 * @author alex.meng
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

    /**
     * spring应用上下文
     * -- GETTER --
     * Gets application context.
     */
    @Getter
    private static ApplicationContext applicationContext;

    /**
     * 注册bean
     *
     * @param beanName bean名称
     * @param bean     bean对象
     */
    public static void registerBean(String beanName, Object bean) {
        applicationContext.getAutowireCapableBeanFactory().autowireBean(bean);
        applicationContext.getAutowireCapableBeanFactory().initializeBean(bean, beanName);
    }

    /**
     * 获取对象
     *
     * @param name the name
     * @return Object bean
     * @throws BeansException the beans exception
     */
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);
    }

    /**
     * 获取对象
     *
     * @param <T>   the type parameter
     * @param clazz the clazz
     * @return Object bean
     * @throws BeansException the beans exception
     */
    public static <T> T getBean(Class<T> clazz) throws BeansException {
        return applicationContext.getBean(clazz);
    }

    public static <T> T getBean(String beanName, Class<T> clazz) {
        return applicationContext.getBean(beanName, clazz);
    }

    public static boolean isVirtual() {
        return Threading.VIRTUAL.isActive(getBean(Environment.class));
    }

    /**
     * 根据配置名称获取配置内容
     *
     * @param key 配置键
     * @return 配置值
     */
    public static String getProperty(String key) {
        return applicationContext.getEnvironment().getProperty(key);
    }

    /**
     * 根据配置名称获取配置内容，如果不存在则返回默认值
     *
     * @param key          配置键
     * @param defaultValue 默认值
     * @return 配置值
     */
    public static String getProperty(String key, String defaultValue) {
        return applicationContext.getEnvironment().getProperty(key, defaultValue);
    }

    /**
     * 根据配置名称获取配置内容并转换为指定类型
     *
     * @param key        配置键
     * @param targetType 目标类型
     * @param <T>        返回类型
     * @return 配置值
     */
    public static <T> T getProperty(String key, Class<T> targetType) {
        return applicationContext.getEnvironment().getProperty(key, targetType);
    }

    /**
     * 根据配置名称获取配置内容并转换为指定类型，如果不存在则返回默认值
     *
     * @param key          配置键
     * @param targetType   目标类型
     * @param defaultValue 默认值
     * @param <T>          返回类型
     * @return 配置值
     */
    public static <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
        return applicationContext.getEnvironment().getProperty(key, targetType, defaultValue);
    }

    /**
     * 获取当前配置文件
     *
     * @return string [ ]
     */
    public String[] getProfiles() {
        return applicationContext.getEnvironment().getActiveProfiles();
    }

    /**
     * 实现ApplicationContextAware接口的回调方法。设置上下文环境
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        synchronized (SpringContextUtil.class) {
            SpringContextUtil.applicationContext = applicationContext;
        }
    }
}
